package service

import (
	"context"
	"fmt"
	"os"
	"path/filepath"
	"time"

	"github.com/example/video_backend/internal/model"
	"github.com/example/video_backend/internal/repository"
	"github.com/example/video_backend/pkg/logger"
	"github.com/example/video_backend/pkg/minio"
	"github.com/example/video_backend/pkg/utils"
	"go.uber.org/zap"
)

// ProxyVideoService 通过代理下载视频的服务接口
type ProxyVideoService interface {
	// DownloadVideoByProxy 通过代理下载视频并上传到MinIO
	DownloadVideoByProxy(ctx context.Context, userID uint, videoURL string, title string, description string, categoryID uint) (*model.Video, error)
}

// proxyVideoService 实现ProxyVideoService接口
type proxyVideoService struct {
	videoRepo      repository.VideoRepository
	categoryRepo   repository.CategoryRepository
	httpClient     *utils.HTTPClient
	clashProxyURL  string
}

// NewProxyVideoService 创建代理视频服务实例
func NewProxyVideoService(
	videoRepo repository.VideoRepository,
	categoryRepo repository.CategoryRepository,
	clashProxyURL string,
) ProxyVideoService {
	return &proxyVideoService{
		videoRepo:      videoRepo,
		categoryRepo:   categoryRepo,
		httpClient:     utils.NewHTTPClient(clashProxyURL),
		clashProxyURL:  clashProxyURL,
	}
}

// DownloadVideoByProxy 通过代理下载视频并上传到MinIO
func (s *proxyVideoService) DownloadVideoByProxy(ctx context.Context, userID uint, videoURL string, title string, description string, categoryID uint) (*model.Video, error) {
	logger.Info("开始通过代理下载视频", 
		zap.String("videoURL", videoURL), 
		zap.Uint("userID", userID),
		zap.String("title", title),
	)

	// 1. 检查分类是否存在
	category, err := s.categoryRepo.GetByID(ctx, categoryID)
	if err != nil {
		return nil, fmt.Errorf("获取分类失败: %w", err)
	}
	if category == nil {
		return nil, fmt.Errorf("分类不存在: %d", categoryID)
	}

	// 2. 创建临时文件路径
	tempDir := os.TempDir()
	timestamp := time.Now().UnixNano()
	ext := filepath.Ext(videoURL)
	if ext == "" {
		// 如果URL中没有扩展名，默认使用.mp4
	ext = ".mp4"
	}
	tempFilePath := filepath.Join(tempDir, fmt.Sprintf("video_temp_%d%s", timestamp, ext))

	// 3. 通过代理下载视频文件
	downloadedPath, err := s.httpClient.DownloadFileWithProxy(ctx, videoURL, tempFilePath)
	if err != nil {
		return nil, fmt.Errorf("下载视频失败: %w", err)
	}
	defer os.Remove(downloadedPath) // 清理临时文件

	// 4. 确保文件存在
	_, err = os.Stat(downloadedPath)
	if err != nil {
		return nil, fmt.Errorf("获取文件信息失败: %w", err)
	}

	// 6. 上传文件到MinIO
	// 使用UploadImageFile函数，它直接接受文件路径
	videoObjectURL, err := minio.UploadImageFile(ctx, downloadedPath, "videos/")
	if err != nil {
		return nil, fmt.Errorf("上传到MinIO失败: %w", err)
	}

	logger.Info("视频上传到MinIO成功", zap.String("videoURL", videoObjectURL))

	// 8. 创建视频记录
	// Video结构体嵌入了gorm.Model，所以它已经包含CreatedAt和UpdatedAt字段
	video := &model.Video{
		Title:         title,
		Description:   description,
		VideoURL:      videoObjectURL,
		CoverURL:      "", // 初始没有封面
		Duration:      0,  // 初始时长为0
		Views:         0,
		LikesCount:    0,
		CommentsCount: 0,
		IsPublic:      true,
		UserID:        userID,
		CategoryID:    categoryID,
	}

	// 9. 保存视频记录到数据库
	if err := s.videoRepo.Create(ctx, video); err != nil {
		return nil, fmt.Errorf("保存视频记录失败: %w", err)
	}

	logger.Info("视频记录创建成功", zap.Uint("videoID", video.ID), zap.Uint("userID", userID))

	return video, nil
}